#include "iic_basen32lib.h"
#include "sht31.h"
#include <stdio.h>

//开启周期测量 0x2236 0xe000

SHT3X_t sht31 = 
{
	.temperature = 0.0f,
	.humidity = 0.0f,
  .temp_integer = 0,
  .temp_decimal = 0,
  .humi_integer = 0,
  .humi_decimal = 0,
};

s_iic_bus_t SHT_bus = 
{
	.IIC_SDA_GPIO = SHT3X_SDA_GPIO,
	.IIC_SCL_GPIO = SHT3X_SCL_GPIO,
	.IIC_SDA_PIN  = SHT3X_SDA_PIN,
	.IIC_SCL_PIN  = SHT3X_SCL_PIN,
};
// 静态函数
static unsigned char SHT3Xcrc8(const unsigned char *data, int len);
static void SHT3X_CheckSelf(void);
#if SHT31_STATE
static uint8_t SHT3X_ReadState(uint8_t *temp);
#endif
static void Cal_TempAndHumi_DispValue(void);
static uint8_t SHT3X_WriteCMD(uint16_t cmd);
//初始化
void SHT3X_Init(void)
{
	
   SHT3X_SCL_CLK_EN();
	 SHT3X_SDA_CLK_EN();                        
   IICInit(&SHT_bus);
	 delay_us(100);
	 SHT3X_CheckSelf();
}



//单次触发 读取SHT30结果 0x2c06
uint8_t SHT3X_GetValue_Once(void)
{
	uint8_t buff[6]={0},i=0;
	uint16_t data_16=0;
	IICStart(&SHT_bus);
	IICSendByte(&SHT_bus, SHT3X_ADDRESS_WRITE );
	if( IICWaitAck(&SHT_bus) == 1 )return 1;
	
	IICSendByte(&SHT_bus, (0x24) );//发送命令的高8位
	if( IICWaitAck(&SHT_bus) == 1 )return 2;
	
  IICSendByte(&SHT_bus, (0x00) );
  if( IICWaitAck(&SHT_bus) == 1 )return 3;
	 //如不使用超时判断，很容易数据错乱  逻辑分析仪掐出来 开启单次转换 等待20ms左右收到回复
        do
        {
							//超时判断
							i++;
							if( i > 20) return 4;
							delay_ms(5);

              IICStart(&SHT_bus);
							IICSendByte(&SHT_bus, SHT3X_ADDRESS_READ );
	
        }while( IICWaitAck(&SHT_bus) == 1);        //读取到温湿度数据则结束读命令


    //温度高8位
        buff[0] =  IICReceiveByte(&SHT_bus,1);
       
    //温度低8位
        buff[1] =  IICReceiveByte(&SHT_bus,1);

     //温度CRC校验值
        buff[2] =  IICReceiveByte(&SHT_bus,1);

    //湿度高8位
        buff[3] =  IICReceiveByte(&SHT_bus,1);

    //湿度低8位
        buff[4] =  IICReceiveByte(&SHT_bus,1);

    //湿度CRC校验值
        buff[5] =  IICReceiveByte(&SHT_bus,0);

        IICStop(&SHT_bus);

    //CRC校验（将要校验的数值带入，查看计算后的校验值是否和读取到的校验值一致）
    if( (SHT3Xcrc8(&buff[0],2) == buff[2]) && ( SHT3Xcrc8(&buff[3],2) == buff[5]) )
        {
        //计算温度值
        data_16 =(buff[0]<<8) | buff[1];
        sht31.temperature = 175.0f * (float)data_16 / 65535.0f - 45.0f;
        //计算湿度值
        data_16 = 0;
        data_16 =(buff[3]<<8) | buff[4];
        sht31.humidity = 100.0f * (float)data_16 / 65535.0f;
				Cal_TempAndHumi_DispValue();
        //printf("temp = %.2f\r\n", sht31.temperature);
        //printf("humi = %.2f\r\n", sht31.humidity);
				delay_us(10);
				
        return 0;
    }
    else
        {
                printf("Check failure!\r\n");
        }
    return 5;
}



//周期触发 读取SHT30结果
uint8_t SHT3X_GetValue_Period(void)
{
			uint16_t i = 0;
			uint16_t data_16 = 0;
			uint8_t buff[6]={0};

      SHT3X_WriteCMD(0x2236); 
			delay_us(100);
			
			IICStart(&SHT_bus);
			
      IICSendByte(&SHT_bus, SHT3X_ADDRESS_WRITE );
			if( IICWaitAck(&SHT_bus) == 1 ){printf("error 1 No device\r\n");return 1;}
	
			IICSendByte(&SHT_bus, (0xe0) );//发送命令的高8位
			if( IICWaitAck(&SHT_bus) == 1 ){printf("error 2 CMDH error\r\n");return 2;}
	
			IICSendByte(&SHT_bus, (0x00) );
			if( IICWaitAck(&SHT_bus) == 1 ){printf("error 3 CMDL error\r\n");return 3;}

    //如不使用超时判断，很容易数据错乱
        do
        {
							//超时判断
							i++;
							if( i > 20) return 4;
							delay_ms(5);

              IICStart(&SHT_bus);
							IICSendByte(&SHT_bus, SHT3X_ADDRESS_READ );
	
        }while( IICWaitAck(&SHT_bus) == 1);        //读取到温湿度数据则结束读命令


    //温度高8位
        buff[0] =  IICReceiveByte(&SHT_bus,1);
       
    //温度低8位
        buff[1] =  IICReceiveByte(&SHT_bus,1);

     //温度CRC校验值
        buff[2] =  IICReceiveByte(&SHT_bus,1);

    //湿度高8位
        buff[3] =  IICReceiveByte(&SHT_bus,1);

    //湿度低8位
        buff[4] =  IICReceiveByte(&SHT_bus,1);

    //湿度CRC校验值
        buff[5] =  IICReceiveByte(&SHT_bus,0);

        IICStop(&SHT_bus);

    //CRC校验（将要校验的数值带入，查看计算后的校验值是否和读取到的校验值一致）
    if( (SHT3Xcrc8(&buff[0],2) == buff[2]) && ( SHT3Xcrc8(&buff[3],2) == buff[5]) )
        {
        //计算温度值
        data_16 =(buff[0]<<8) | buff[1];
        sht31.temperature = 175.0f * (float)data_16 / 65535.0f - 45.0f;
        //计算湿度值
        data_16 = 0;
        data_16 =(buff[3]<<8) | buff[4];
        sht31.humidity = 100.0f * (float)data_16 / 65535.0f;
				Cal_TempAndHumi_DispValue();
        //printf("temp = %.2f\r\n", sht31.temperature);
        //printf("humi = %.2f\r\n", sht31.humidity);
				delay_us(10);
				
        return 0;
    }
    else
        {
                printf("Check failure!\r\n");
        }
    return 5;
}



//自检
static void SHT3X_CheckSelf(void)
{
		IICStart(&SHT_bus);
    IICSendByte(&SHT_bus, SHT3X_ADDRESS);

	  if( IICWaitAck(&SHT_bus) != 0  )	
		{
			#if PrintSHT31
			 printf("No SHT31\r\n");
			#endif
		
		}else 
		{
			#if PrintSHT31
			printf("Get SHT31\r\n");
			#endif
		}
		
	  IICStop(&SHT_bus);
}

#if SHT31_STATE
//读取SHT30寄存器状态
static uint8_t SHT3X_ReadState(uint8_t *temp)
{
    IICStart(&SHT_bus);
    IICSendByte(&SHT_bus, SHT3X_ADDRESS_WRITE);
	  if( IICWaitAck(&SHT_bus) == 1 )return 1;
	  
    IICSendByte(&SHT_bus, 0xf3);
    if( IICWaitAck(&SHT_bus) == 1 )return 2;
	  
		IICSendByte(&SHT_bus, 0X2d); 
    if( IICWaitAck(&SHT_bus) == 1 )return 3;
    
    IICStart(&SHT_bus);
    IICSendByte(&SHT_bus, SHT3X_ADDRESS_READ );
    if( IICWaitAck(&SHT_bus) == 1 ) return 4;
 
    
    temp[0] = IICReceiveByte(&SHT_bus,1);//高
    temp[1] = IICReceiveByte(&SHT_bus,1);//低
    temp[2] = IICReceiveByte(&SHT_bus,0);//校验
    IICStop(&SHT_bus);
	  return 0;
}
#endif
//将得到的浮点型数据转换为整数和小数分别存储
static void Cal_TempAndHumi_DispValue(void)
{
    // 温度边界检查
    if (sht31.temperature > 125.0f)
    {
        sht31.temp_integer = 125;
        sht31.temp_decimal = 0;
        return;
    }
    else if (sht31.temperature < -40.0f)
    {
        sht31.temp_integer = -40;
        sht31.temp_decimal = 0;
        return;
    }

    // 湿度边界检查
    if (sht31.humidity > 100.0f)
    {
        sht31.humi_integer = 100;
        sht31.humi_decimal = 0;
        return;
    }
    else if (sht31.humidity < 0.0f)
    {
        sht31.humi_integer = 0;
        sht31.humi_decimal = 0;
        return;
    }

    // 分离湿度整数和小数部分
    sht31.humi_integer = (short)sht31.humidity;
    sht31.humi_decimal = (short)((sht31.humidity - (float)sht31.humi_integer) * 10.0f);

    // 分离温度整数和小数部分
    sht31.temp_integer = (char)sht31.temperature;
    sht31.temp_decimal = (char)((sht31.temperature - (float)sht31.temp_integer) * 10.0f);

    // 确保温度小数部分为正值
    if (sht31.temp_decimal < 0)
    {
        sht31.temp_decimal = - sht31.temp_decimal;
    }
}
// 写命令
uint8_t SHT3X_WriteCMD(uint16_t cmd)
{
  IICStart(&SHT_bus);
  IICSendByte(&SHT_bus, SHT3X_ADDRESS_WRITE );
	if( IICWaitAck(&SHT_bus) == 1 )return 1;
	
	IICSendByte(&SHT_bus, (cmd>>8) );//发送命令的高8位
	if( IICWaitAck(&SHT_bus) == 1 )return 2;
	
  IICSendByte(&SHT_bus, (cmd&0xFF) );
  if( IICWaitAck(&SHT_bus) == 1 )return 3;
  //IICStop(&SHT_bus);
	return 0;
}

static unsigned char SHT3Xcrc8(const unsigned char *data, int len)
{
        const unsigned char POLYNOMIAL = 0x31;
        unsigned char crc = 0xFF;
        int j, i;

        for (j=0; j<len; j++)
        {
                crc ^= *data++;
                for ( i = 0; i <8; i++ )
                {
                        crc = ( crc & 0x80 ) ? (crc << 1) ^ POLYNOMIAL : (crc << 1);
                }
        }
        return crc;
}
